
/**
 * 通用工具-类
 */
import pako from 'pako' // gzip 压缩|解压
import axios from 'axios' // 引入全局
// const cheerio = require('cheerio') // 加载cheerio node.js 转换dom节点 和jQuery功能基本一样

/* 获取当前时间-或转换 yyyy-MM-dd hh:mm:ss|yyyy-MM-dd */
export function getDataTimeToStr(timeNum, fmt = 'yyyy-MM-dd hh:mm:ss') {
  var date = timeNum ? new Date(timeNum) : new Date()
  return format(fmt, date)
}
/*
* 传入的数组有id和父节点pid字段，通过它们的关联构造成一棵或多棵树结构
* @param nodes 集合
* @param treeRootId 根节点的id
* @param idS 根节点的id == key 可以不是id
* @param pidS 根节点的id == parent 可以不是pid
*/
export function createTreeDataStr(nodes, treeRootId, idS, pidS) {
  var id = idS || 'id'
  var pid = pidS || 'pid'
  var groups = {}
  // 按父节点将节点分组
  for (var i in nodes) {
    if (!groups[nodes[i][pid]]) {
      groups[nodes[i][pid]] = []
    }
    groups[nodes[i][pid]].push(nodes[i])
    if (treeRootId && treeRootId === nodes[i][id]) { // 发现传入的根节点id作为节点id时，将根节点设置为该节点的父节点
      treeRootId = nodes[i][pid]
    }
  }

  var rootNodes = groups[treeRootId]
  groups[treeRootId] = null // [SAFEGUARD]防止自为父节点或互为父节点（有环图结构）导致的死循环
  function traverseTreeNodeGroup(treeNodeGroup) {
    for (var i in treeNodeGroup) {
      var node = treeNodeGroup[i]
      if (groups[node[id]]) {
        node.children = groups[node[id]]
        groups[node[id]] = null // [SAFEGUARD]防止自为父节点或互为父节点（有环图结构）导致的死循环
        traverseTreeNodeGroup(node.children)
      }
    }
  }
  traverseTreeNodeGroup(rootNodes)
  return rootNodes
}
/**
 * 移除children 为空
 */
export function removeTree(list) {
  var this_ = this
  for (var i in list) {
    if (list[i].children.length == 0) {
      list[i].children = undefined
    } else {
      this_.removeTree(list[i].children)
    }
  }
  return list
}

/**
 * 时间格式化处理
 */
export function format(fmt, date) { // author: meizz
  var o = {
    'M+': date.getMonth() + 1, // 月份
    'd+': date.getDate(), // 日
    'h+': date.getHours(), // 小时
    'm+': date.getMinutes(), // 分
    's+': date.getSeconds(), // 秒
    'q+': Math.floor((date.getMonth() + 3) / 3), // 季度
    'S': date.getMilliseconds() // 毫秒
  }
  if (/(y+)/.test(fmt)) {
    fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length))
  }
  for (var k in o) {
    if (new RegExp('(' + k + ')').test(fmt)) {
      fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length)))
    }
  }
  return fmt
}
/**
 * gzip - 压缩解压
 * @param str 要压缩|解压的内容
 * @param bool false 压缩 true 解压 默认压缩
 */
export function gzip(str, bool) {
  if (str) {
    if (!bool) { // 压缩
      // escape(str)  --->压缩前编码，防止中午乱码
      return pako.gzip(escape(str), { to: 'string' })
    } else { // 解压
      // 将二进制字符串转换为字符数组
      var charData = str.split('').map((x) => { return x.charCodeAt(0) })
      // console.log('压缩后的文件大小:', charData.join(','))

      // 将数字数组转换成字节数组
      var binData = new Uint8Array(charData)

      // 解压
      var data = pako.inflate(binData)

      // 将GunZip ByTAREAR转换回ASCII字符串
      const res = String.fromCharCode.apply(null, new Uint16Array(data))

      // unescape(str)  --->解压后解码，防止中午乱码
      return unescape(res)
    }
  }
}
/**
 * 将以base64的图片url数据转换为Blob
 * @param urlData base64地址: 'data:image/png;base64,~~~~'
 * 用url方式表示的base64图片数据
 */
export function convertBase64UrlToBlob(urlData) {
  var arr = urlData.split(',')
  var mime = arr[0].match(/:(.*?);/)[1]

  // 处理异常,将ascii码小于0的转换为大于0
  var bstr = atob(arr[1])
  var n = bstr.length
  var u8arr = new Uint8Array(n)
  while (n--) {
    u8arr[n] = bstr.charCodeAt(n)
  }
  return new Blob([u8arr], { type: mime })
}
/**
 * @param {*} value 要转换的值 |必填 - 是
 * @param {*} ratio 比例值 |必填 - 否 默认10000
 * @param {*} bit 保留小数位 |必填 - 否
 * @param {*} type 类型 1 向上取 2 向下取 3 四舍五入
 */
export function toMoney(value, ratio = 10000, bit = 1, type = 1) {
  // return bit && bit > 0 ? parseFloat((value / ratio).toFixed(bit)) : (value / ratio)
  if (ratio < 10) { // 位数
    type = bit
    bit = ratio
    ratio = 10000
  }
  let bitNum = 1
  while (bit > 0) {
    bit--; bitNum *= 10
  }
  const fn = ['ceil', 'floor', 'round'][type - 1]
  return Math[fn](value / ratio * bitNum) / bitNum
}
/**
 * @description 图片资源解密
 * @param {*} url 资源地址
 * @param {*} key 解密key
 */
export function ImgDeCodeURL(url, key = 10844680) {
  key = (Number)(key) // 类型转换
  const callback = (resolve, reject) => {
    axios.get(url, { responseType: 'arraybuffer' }).then(res => {
      if (res.status == 200) {
        const arrayBuff = res.data
        const uint8Arr = new Uint8Array(arrayBuff)
        if (uint8Arr && uint8Arr.byteLength) {
          for (let i = 0; i < 100 && i < uint8Arr.byteLength; ++i) {
            uint8Arr[i] = uint8Arr[i] ^ key
          }
          const blob = new Blob([uint8Arr.buffer])
          return resolve(blob)
        }
      }
      return reject()
    }).catch(_ => { return reject() })
  }
  return new Promise(callback)
}
/**
 * @param {*} columns 设置 [key]字段/[value]列名 列: {id:'ID', name: '姓名'}
 * @param {*} list 服务端返回数据 数组[]
 * @param {*} fileName 文件名
 */
export function export2Excel(columns, list, fileName) {
  require.ensure([], () => { // 代码打包分离
      const { export_json_to_excel } = require('../excel/Export2Excel')
      let tHeader = []
      let filterVal = []
      console.log(columns)
      if (!columns) {
          return
      }
      // columns.forEach(item => {
      //     tHeader.push(item.title)
      //     filterVal.push(item.key)
      // })
      tHeader = Object.values(columns)
      filterVal = Object.keys(columns)
      const data = list.map(v => filterVal.map(j => v[j]))
      export_json_to_excel(tHeader, data, fileName)
  })
}
// 获取新对象
export function createObj(obj, arr) {
  // const pick = (obj, arr) => arr.reduce((iter, val) => (val in obj && (iter[val] = obj[val]), iter), {});
  return arr.reduce((iter, val) => {
    if (val in obj) {
      iter[val] = obj[val]
    }
    return iter
  }, {})
}
// 随机数 范围 min|小 max|大
export function random(min, max) {
  return parseInt(Math.random() * (max - min + 1) + min, 10)
}

/** js加密 */
export function enCode(str) {
  return window.btoa(unescape(encodeURIComponent(str)))
}
/** js解密 */
export function deCode(str) {
  return decodeURIComponent(escape(window.atob(str)))
}
/**
 * copy 需自己引入依赖和代码
 * 例:
   <!-- 复制按钮 -->
   <span ref="copy"></span>
 * import Clipboard from 'clipboard' // 复制插件
 * @param Clipboard 引入的插件
 * @param copyDom dom对象 例: this.$refs.copy
 * @param copyText 要复制的内容
 * @param this_ 是否需要默认-提示
 * */
export function copyData(Clipboard, copyDom, copyText, this_) {
  return new Promise((resolve, reject) => {
    const clipboard = new Clipboard(copyDom, {
      text: () => { return copyText }
    })
    // 复制成功-回调
    clipboard.on('success', (e) => {
      if (this_) {
        this_.$notify.success({ message: '复制成功', iconClass: 'fa fa-check' })
      }
      e.clearSelection() // 清除选中状态
      clipboard.destroy() // 销毁复制对象-实例
      resolve(e)
    })
    // 复制失败-回调
    clipboard.on('error', (e) => {
      // console.info('错误', e)
      if (this_) {
        this_.$notify.error({ message: '复制失败', iconClass: 'fa fa-close' })
      }
      reject(e)
    })
    // 手动触发
    copyDom.click()
  })
}

// 验证-返回对象
export function getRulesStr(required = false, num, msg, option) {
  if (typeof required == 'number') { // 全部往前移
    option = msg
    msg = num
    num = required
    required = false
  }
  msg = msg || `请输入${num}字以内的字符`
  const o = { required: required, max: num, message: msg, trigger: 'blur' }
  return Object.assign(o, option)
}
// js-生成UUID
export function generateUUID() {
  var d = new Date().getTime()
  var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
    var r = (d + Math.random() * 16) % 16 | 0
    d = Math.floor(d / 16)
    return (c == 'x' ? r : (r & 0x3 | 0x8)).toString(16)
  })
  return uuid
}
// 对象复制-不创建新对象-不覆盖属性-驼峰也过滤
export function copyObj(o, c) {
  const isNe = (k) => {
    const k1 = k.replace(/([A-Z])/g, '-$1').toLowerCase()
    const k2 = k.replace(/\-(\w)/g, (all, letter) => letter.toUpperCase())
    return !o.hasOwnProperty(k1) && !o.hasOwnProperty(k2)
  }
  Object.keys(c)
    .filter(k => isNe(k))
    .forEach(k => { o[k] = c[k] })
  return o
}

// 字段合计 row 参数 props 需要合并字段数组
export function tableSummary(row, props, cb, defVal = '') {
  const { columns, data } = row
  const add = (n1, n2) => {
    var r1, r2, m
    try { r1 = n1.toString().split('.')[1].length } catch (e) { r1 = 0 }
    try { r2 = n2.toString().split('.')[1].length } catch (e) { r2 = 0 }
    m = Math.pow(10, Math.max(r1, r2))
    return (n1 * m + n2 * m) / m
  }
  const sum = (prop) => {
    return data.map(o => isNaN(Number(o[prop])) ? 0 : Number(o[prop]))
      .reduce((r, c) => { return add(r, c) }, 0)
  }
  return columns.reduce((r, c, i) => {
    const prop = c.property
    const bool = props && props.includes(prop)
    const total = bool ? sum(prop) : 0
    const sumVal = cb ? cb(total, i, c, r) : total
    r[i] = bool || sumVal ? sumVal : defVal
    return r
  }, [])
}
